<?php
/**
 * 
 * @todo description of this class
 * 
 * @author Alton Crossley <crossleyframework@nogahidebootstrap.com>
 * @package Crossley Framework
 *  
 * @copyright Copyright (c) 2003-2009, Nogaide BootStrap INC. All rights reserved.
 * @license BSD http://opensource.org/licenses/bsd-license.php
 * @version $Id:$
 * 
 */
class X_Date
{
	const MINUTE = 60;
	
	const HOUR = 3600;
	
	const DAY = 86400;
	
	public $sFormat = 'm/d/Y g:i:s a';
	
	private $_unixtime;
	
	public function __construct($sDate = null)
	{
		if (!empty($sDate))
		{
			$this->setWithString($sDate);
		}
		else
		{
			$this->_unixtime = time();
		}				
	}
	
	/**
	 * set datetime using any string parcable by strtotime
	 * @param unknown_type $sDateTime
	 */
	public function setWithString($sDateTime)
	{
		$this->_unixtime = strtotime($sDateTime);
		$this->_check();
		return $this;
	}
	
	/**
	 * return a formated date string
	 * @param string $sFormat
	 * @return string
	 */
	public function toString($sFormat = null, $sType = null)
	{
		$this->_check();
		$sCurrentFormat = (empty($sFormat)) ? $this->sFormat : $sFormat;
		// print X_Debug::out('format: ' . $sCurrentFormat . ' - ' . $this->_unixtime . ' - ' . date($sCurrentFormat, $this->_unixtime));
		return date($sCurrentFormat, $this->_unixtime);
	}
	
	/**
	 * set datetime using a unix time stamp
	 * @param integer $iUnixTime
	 */
	public function setTimestamp($iUnixTime)
	{
		$this->_unixtime = $iUnixTime;
		$this->_check();
		return $this;
	}
	
	/**
	 * return the unix time stamp
	 * @return integer
	 */
	public function getTimestamp()
	{
		$this->_check();
		return $this->_unixtime;
	}
	/**
	 * add seconds
	 * @param integer $iCount number of seconds
	 */
	public function addSecond($iCount = 1)
	{
		$this->_check();
		$this->_unixtime += $iCount;
		return $this;
	}
	/**
	 * subtract seconds
	 * @param integer $iCount number of seconds
	 */
	public function subtractSecond($iCount = 1)
	{
		$this->_check();
		$this->_unixtime -= $iCount;
		return $this;
	}
	/**
	 * add minutes
	 * @param integer $iCount number of munutes
	 */
	public function addMinute($iCount = 1)
	{
		return $this->_addStringTime($iCount, 'min');
	}
	/**
	 * subtract minutes
	 * @param integer $iCount number of minutes
	 */
	public function subtractMinute($iCount = 1)
	{
		return $this->_subtractStringTime($iCount, 'min');
	}
	/**
	 * add hours
	 * @param integer $iCount numbers of hours
	 */
	public function addHour($iCount = 1)
	{
		return $this->_addStringTime($iCount, 'hour');
	}
	/**
	 * subtract hours
	 * @param integer $iCount number of hours
	 */
	public function subtractHour($iCount = 1)
	{
		return $this->_subtractStringTime($iCount, 'hour');
	}
	/**
	 * add days
	 * @param integer $iCount number of days
	 */
	public function addDay($iCount = 1)
	{
		return $this->_addStringTime($iCount, 'day');
	}
	/**
	 * subtract days
	 * @param integer $iCount number of days
	 */
	public function subtractDay($iCount = 1)
	{
		return $this->_subtractStringTime($iCount, 'day');
	}
	/**
	 * set the day of the month by its number
	 * @param integer $iDay
	 */
	public function setDayOfMonth($iDay = 1)
	{
		$this->setWithString($this->toString("m/{$iDay}/Y g:i:s a"));
		$this->_check();
		return $this;
	}
	
	public function addMonth($iCount = 1)
	{
		return $this->_addStringTime($iCount, 'month');
	}

	public function subtractMonth($iCount = 1)
	{
		return $this->_subtractStringTime($iCount, 'month');
	}
	
	private function _addStringTime($iCount, $sUnit)
	{
		$this->_unixtime = strtotime('+' . $iCount . ' ' . $sUnit, $this->_unixtime);
		$this->_check();
		return $this;
	}
	
	private function _subtractStringTime($iCount, $sUnit)
	{
		$this->_unixtime = strtotime('-' . $iCount . ' ' . $sUnit, $this->_unixtime);
		$this->_check();
		return $this;
	}
		
	public function setLastDayOfMonth()
	{
		return $this->addMonth()->setDayOfMonth(1)->subtractDay();
	}
	
	public function zeroTime()
	{
		$this->setWithString($this->toString('m/d/Y'));
		return $this;
	}
	
	/**
	 * return if a date is earlier
	 * @param X_Date $oDate
	 * @return bool
	 */
	public function isEarlier($Date)
	{
//		print X_Debug::out((string)$this . " (this) is earlier (date) " . (string)$Date);
		$this->_check();
		if ($Date instanceof X_Date)
		{
			return ($this->_unixtime < $Date->getTimestamp());			
		}
		else
		{
			$tmpDate = new X_Date((string)$Date);
			return ($this->_unixtime < (int)$tmpDate->getTimestamp());
		}
	}
	
	/**
	 * return if a date is later
	 * @param X_Date $oDate
	 * @return bool
	 */
	public function isLater(X_Date $oDate)
	{
		$this->_check();
		return ($this->_unixtime < $oDate->getTimestamp());		
	}
	
	public function isValid()
	{
		return (bool)($this->_unixtime);		
	}
	
	private function _check()
	{
		if ($this->isValid()) return true;
		
		throw new X_Exception('invalid date set on X_Date ('.$this->_unixtime.')');		
	}
	
	/**
	 * format date and return it as string
	 * @param $sFormat
	 */
	function __toString()
	{
		return $this->toString();
	}
}